import asyncio
import json
import os
import sys
import websockets
from jsonpath import jsonpath

from PyQt5.QtCore import QCoreApplication, QTimer
from PyQt5.QtWidgets import QWidget, QApplication, QMessageBox
from PyQt5 import QtCore
from PyQt5.QtCore import QThread, pyqtSignal

from main_ui import MianUi
from toast_ui import ToastUi

"""
TOP_OPTION_COLOR 投票数多的选项颜色
DEFAULT_TEXT_COLOR 默认文本颜色
WEB_SOCKET_URI WebSocket服务器的地址
"""

TOP_OPTION_COLOR = "color: rgb(118, 248, 255);"
DEFAULT_TEXT_COLOR = "color: rgb(255, 255, 255);"
WEB_SOCKET_URI = "ws://127.0.0.1:12345/"


# 定义一个计时器线程
class CountdownTimer(QThread):
    # 定义一个信号，当计时结束时发送
    countdown_finished = pyqtSignal()
    # 定义一个信号，每秒发送
    countdown_update = pyqtSignal(str)

    def __init__(self, seconds, parent=None):
        super().__init__(parent)
        self.timer = None
        self.seconds = seconds
        self.stop_flag = True

    def run(self):
        # 创建一个QTimer对象
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_timer)
        self.timer.start(1000)  # 每秒触发一次

        # 开始事件循环
        self.exec_()

    def update_timer(self):
        if self.stop_flag is False:
            self.timer.stop()
            self.quit()
            return
        if self.seconds > 0:
            self.seconds -= 1
            # 发送剩余的时间
            self.countdown_update.emit(str(self.seconds))
        else:
            self.timer.stop()
            self.countdown_finished.emit()  # 发送信号通知主线程
            self.quit()


# 定义一个WebSocket监听线程
class WebSocketThread(QThread):
    # 定义一个信号，当接收到消息时发送
    message_received = pyqtSignal(dict)
    room_info = pyqtSignal(str)

    def __init__(self, uri, token, parent=None):
        super().__init__(parent)
        self.uri = uri
        self.token = token
        self.check_flag = True

    def run(self):
        asyncio.run(self.main())

    async def handle_message(self, message):
        msg_type = message.get("Type")
        if msg_type == 1:
            data = json.loads(message.get("Data"))
            user_name = jsonpath(data, '$.User.Nickname')[0]
            user_level = jsonpath(data, '$.User.PayLevel')[0]
            user_msg = jsonpath(data, '$.Content')[0]
            return_json = {
                "user_name": user_name,
                "user_level": user_level,
                "user_msg": user_msg
            }
            self.message_received.emit(return_json)
        elif msg_type == 6:
            data = json.loads(message.get("Data"))
            room_info = jsonpath(data, '$.Content')[0]
            # 当前直播间人数 868，累计直播间人数 29.9万
            # 获取当前直播间人数
            current_room_num = room_info.split("，")[0].split(" ")[1]
            self.room_info.emit(current_room_num)

    async def main(self):
        async with websockets.connect(self.uri) as websocket:
            await websocket.send(self.token)
            print("Sent token to server")

            try:
                while self.check_flag:
                    message = await websocket.recv()
                    await self.handle_message(json.loads(message))
            except websockets.ConnectionClosed:
                print("Connection closed")


# 定义一个Toast窗口
class MainUiToast(QWidget):
    def __init__(self, config, parent=None):
        super(MainUiToast, self).__init__(parent)
        self.MianUi = ToastUi()
        self.MianUi.setupUi(self)

        # 窗口置顶 + 透明
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.setWindowTitle("提示")
        # 获取输入框的值
        self.title = config.MianUi.lineEdit.text()
        self.listen_time = config.MianUi.lineEdit_2.text()
        self.option1_str = config.MianUi.lineEdit_3.text()
        self.option1_listen = config.MianUi.lineEdit_4.text()
        self.option2_str = config.MianUi.lineEdit_5.text()
        self.option2_listen = config.MianUi.lineEdit_6.text()
        self.admission_repeat_request = config.MianUi.checkBox.isChecked()
        self.listen_in_msg = config.MianUi.checkBox_2.isChecked()

        if self.admission_repeat_request is False:
            print('不允许重复投票')
            self.no_admission_repeat_request = True
            self.repeat_request_username_list = []
        else:
            self.no_admission_repeat_request = False


        self.check_flag = True
        self.option1_num = 0
        self.option2_num = 0

        print(self.title, self.listen_time, self.option1_str, self.option1_listen, self.option2_str,
              self.option2_listen)
        self.MianUi.label.setText(self.title)
        self.MianUi.label_8.setText("00:00")
        self.MianUi.label_2.setText(self.option1_listen)
        self.MianUi.label_3.setText(self.option1_str)
        self.MianUi.label_4.setText('0票')
        self.MianUi.label_5.setText(self.option2_listen)
        self.MianUi.label_6.setText(self.option2_str)
        self.MianUi.label_7.setText('0票')

        # 初始化鼠标拖动相关变量
        self._is_dragging = False
        self._drag_start_position = QtCore.QPoint()

        # self.set_top_option(2)
        self.set_default_option()

        # 启动时间监听
        self.timer_thread = CountdownTimer(int(self.listen_time))
        self.timer_thread.countdown_finished.connect(self.on_countdown_finished)
        self.timer_thread.countdown_update.connect(self.on_countdown_update)
        self.timer_thread.start()

        # 启动websocket监听
        self.websocket_thread = WebSocketThread(WEB_SOCKET_URI, "token")
        self.websocket_thread.message_received.connect(self.on_message_received)
        self.websocket_thread.room_info.connect(self.room_info_received)
        self.websocket_thread.start()

    def check_repeat_request(self, user_name):
        if self.no_admission_repeat_request:
            if user_name in self.repeat_request_username_list:
                return False
            else:
                self.repeat_request_username_list.append(user_name)
                return True
        else:
            return True

    # 接收到消息
    def on_message_received(self, message):
        print(message)
        if self.listen_in_msg:
            if self.option1_listen in message["user_msg"]:
                if self.check_repeat_request(message["user_name"]):
                    self.option1_num += 1
                    self.MianUi.label_4.setText(f"{self.option1_num}票")
            elif self.option2_listen in message["user_msg"]:
                if self.check_repeat_request(message["user_name"]):
                    self.option2_num += 1
                    self.MianUi.label_7.setText(f"{self.option2_num}票")
        else:
            if message["user_msg"] == self.option1_listen:
                if self.check_repeat_request(message["user_name"]):
                    self.option1_num += 1
                    self.MianUi.label_4.setText(f"{self.option1_num}票")
            elif message["user_msg"] == self.option2_listen:
                if self.check_repeat_request(message["user_name"]):
                    self.option2_num += 1
                    self.MianUi.label_7.setText(f"{self.option2_num}票")

        # 判断谁大
        if self.option1_num > self.option2_num:
            self.set_top_option(1)
        elif self.option1_num < self.option2_num:
            self.set_top_option(2)

    # 更新房间人数
    def room_info_received(self, current_room_num):
        self.MianUi.label_9.setText(f"房间人数：{current_room_num}")

    # 计时完成
    def on_countdown_finished(self):
        print('计时完成')
        self.check_flag = False
        self.timer_thread.stop_flag = False
        self.websocket_thread.check_flag = False

    # 更新时间
    def on_countdown_update(self, seconds):
        # 如果大于60秒，显示分钟
        set_str = ''
        if int(seconds) > 60:
            minutes = int(seconds) // 60
            seconds = int(seconds) % 60
            if minutes < 10:
                set_str += f"0{minutes}:"
            if seconds < 10:
                set_str += f"0{seconds}"
        else:
            if int(seconds) < 10:
                set_str += f"00:0{seconds}"
            else:
                set_str += f"00:{seconds}"
        self.MianUi.label_8.setText(set_str)

    # 鼠标拖动事件
    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self._is_dragging = True
            self._drag_start_position = event.globalPos() - self.frameGeometry().topLeft()
            event.accept()

    # 鼠标移动事件
    def mouseMoveEvent(self, event):
        if self._is_dragging:
            self.move(event.globalPos() - self._drag_start_position)
            event.accept()

    # 鼠标释放事件
    def mouseReleaseEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self._is_dragging = False
            event.accept()

    # 重写关闭事件
    def closeEvent(self, event):
        print('关闭')
        self.check_flag = False
        self.timer_thread.stop_flag = False
        self.websocket_thread.check_flag = False

    # 设置顶部选项
    def set_top_option(self, option_num):
        if option_num == 1:
            # self.MianUi.widget_2.setStyleSheet("#widget_2 {\n"
            #                           "background-color: rgba(0, 0, 0, 40);\n"
            #                           "border-radius: 5px;\n"
            #                           "}")
            # self.MianUi.widget.setStyleSheet("#widget {\n"
            #                             "background-color: rgba(231, 231, 231, 200);\n"
            #                             "border-radius: 5px;\n"
            #                             "}")
            self.MianUi.label_2.setStyleSheet(TOP_OPTION_COLOR)
            self.MianUi.label_3.setStyleSheet(TOP_OPTION_COLOR)
            self.MianUi.label_4.setStyleSheet(TOP_OPTION_COLOR)
            self.MianUi.label_5.setStyleSheet(DEFAULT_TEXT_COLOR)
            self.MianUi.label_6.setStyleSheet(DEFAULT_TEXT_COLOR)
            self.MianUi.label_7.setStyleSheet(DEFAULT_TEXT_COLOR)
        else:
            # self.MianUi.widget.setStyleSheet("#widget {\n"
            #                           "background-color: rgba(0, 0, 0, 40);\n"
            #                           "border-radius: 5px;\n"
            #                           "}")
            # self.MianUi.widget_2.setStyleSheet("#widget_2 {\n"
            #                             "background-color: rgba(231, 231, 231, 200);\n"
            #                             "border-radius: 5px;\n"
            #                             "}")
            self.MianUi.label_2.setStyleSheet(DEFAULT_TEXT_COLOR)
            self.MianUi.label_3.setStyleSheet(DEFAULT_TEXT_COLOR)
            self.MianUi.label_4.setStyleSheet(DEFAULT_TEXT_COLOR)
            self.MianUi.label_5.setStyleSheet(TOP_OPTION_COLOR)
            self.MianUi.label_6.setStyleSheet(TOP_OPTION_COLOR)
            self.MianUi.label_7.setStyleSheet(TOP_OPTION_COLOR)

    # 设置默认选项
    def set_default_option(self):
        self.MianUi.widget.setStyleSheet("#widget {\n"
                                         "background-color: rgba(0, 0, 0, 40);\n"
                                         "border-radius: 5px;\n"
                                         "}")
        self.MianUi.widget_2.setStyleSheet("#widget_2 {\n"
                                           "background-color: rgba(0, 0, 0, 40);\n"
                                           "border-radius: 5px;\n"
                                           "}")
        self.MianUi.label_2.setStyleSheet(DEFAULT_TEXT_COLOR)
        self.MianUi.label_3.setStyleSheet(DEFAULT_TEXT_COLOR)
        self.MianUi.label_4.setStyleSheet(DEFAULT_TEXT_COLOR)
        self.MianUi.label_5.setStyleSheet(DEFAULT_TEXT_COLOR)
        self.MianUi.label_6.setStyleSheet(DEFAULT_TEXT_COLOR)
        self.MianUi.label_7.setStyleSheet(DEFAULT_TEXT_COLOR)


# 主窗口
class MainUiApp(QWidget):
    def __init__(self, parent=None):
        super(MainUiApp, self).__init__(parent)
        self.listen_in_msg = None
        self.admission_repeat_request = None
        self.toast = None
        self.MianUi = MianUi()
        self.MianUi.setupUi(self)
        self.setWindowTitle("抖音投票监听，不知名网友i")

        try:
            if os.path.exists("config.json"):
                self.read_config()
        except Exception as e:
            print('读取配置失败', str(e))

        # 获取输入框的值
        self.title = self.MianUi.lineEdit.text()
        self.listen_time = self.MianUi.lineEdit_2.text()
        self.option1_str = self.MianUi.lineEdit_3.text()
        self.option1_listen = self.MianUi.lineEdit_4.text()
        self.option2_str = self.MianUi.lineEdit_5.text()
        self.option2_listen = self.MianUi.lineEdit_6.text()

        # 绑定按钮事件
        self.MianUi.pushButton_5.clicked.connect(self.start_listen)
        self.MianUi.pushButton_6.clicked.connect(self.stop_listen)
        self.MianUi.pushButton_7.clicked.connect(self.save_config)

    # 检查输入框是否为空
    def check_lineedit_is_null(self):
        # 获取输入框的值
        self.title = self.MianUi.lineEdit.text()
        self.listen_time = self.MianUi.lineEdit_2.text()
        self.option1_str = self.MianUi.lineEdit_3.text()
        self.option1_listen = self.MianUi.lineEdit_4.text()
        self.option2_str = self.MianUi.lineEdit_5.text()
        self.option2_listen = self.MianUi.lineEdit_6.text()
        self.admission_repeat_request = self.MianUi.checkBox.isChecked()
        self.listen_in_msg = self.MianUi.checkBox_2.isChecked()

        # 判断输入框是否为空
        if self.title == "" or self.listen_time == "" or self.option1_str == "" or self.option1_listen == "" or self.option2_str == "" or self.option2_listen == "":
            QMessageBox.warning(self, "警告", "输入框不能为空")
            return False

        # 判断输入框是否为数字
        if not self.listen_time.isdigit():
            QMessageBox.warning(self, "警告", "监听必须为数字")
            return False

        return True

    # 启动监听
    def start_listen(self):
        # 获取输入框的值
        if not self.check_lineedit_is_null():
            return

        # 启动监听
        self.toast = MainUiToast(self)
        self.toast.show()

    # 停止监听
    def stop_listen(self):
        print('停止监听')

        if self.toast is not None:
            self.toast.close()
            self.toast = None

    # 保存配置
    def save_config(self):
        if not self.check_lineedit_is_null():
            return
        with open("config.json", "w") as f:
            config_json = {
                "title": self.title,
                "listen_time": self.listen_time,
                "option1_str": self.option1_str,
                "option1_listen": self.option1_listen,
                "option2_str": self.option2_str,
                "option2_listen": self.option2_listen,
                "admission_repeat_request": self.admission_repeat_request,
                "listen_in_msg": self.listen_in_msg
            }
            f.write(json.dumps(config_json))

        # 提示保存成功
        QMessageBox.warning(self, "提示", "保存成功")

    # 读取配置
    def read_config(self):
        with open("config.json", "r") as f:
            config_json = f.read()
            config_json = json.loads(config_json)
        # 赋值给输入框
        self.MianUi.lineEdit.setText(config_json["title"])
        self.MianUi.lineEdit_2.setText(config_json["listen_time"])
        self.MianUi.lineEdit_3.setText(config_json["option1_str"])
        self.MianUi.lineEdit_4.setText(config_json["option1_listen"])
        self.MianUi.lineEdit_5.setText(config_json["option2_str"])
        self.MianUi.lineEdit_6.setText(config_json["option2_listen"])
        self.MianUi.checkBox.setChecked(config_json["admission_repeat_request"])
        self.MianUi.checkBox_2.setChecked(config_json["listen_in_msg"])

    # 重写关闭事件
    def closeEvent(self, event):
        reply = QMessageBox.question(self, '退出', '你确定要退出吗？', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.stop_listen()
            event.accept()
        else:
            event.ignore()


if __name__ == "__main__":
    QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)  # 高分辨率屏幕适配
    app = QApplication(sys.argv)
    ui = MainUiApp()
    ui.show()
    sys.exit(app.exec_())
